home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Misc / msql-1.0.6 / src / msql / msql_proc.c < prev    next >
C/C++ Source or Header  |  1995-05-28  |  14KB  |  786 lines

  1. /*
  2. **    msql_proc.c    - 
  3. **
  4. **
  5. ** Copyright (c) 1993  David J. Hughes
  6. **
  7. ** Permission to use, copy, and distribute for non-commercial purposes,
  8. ** is hereby granted without fee, providing that the above copyright
  9. ** notice appear in all copies and that both the copyright notice and this
  10. ** permission notice appear in supporting documentation.
  11. **
  12. ** This software is provided "as is" without any expressed or implied warranty.
  13. **
  14. ** ID = "$Id:"
  15. **
  16. */
  17.  
  18.  
  19. #ifndef lint
  20. static char RCS_id[] = 
  21.     "msql_proc.c,v 1.3 1994/08/19 08:03:15 bambi Exp";
  22. #endif 
  23.  
  24.  
  25. #include <stdio.h>
  26. #include <sys/types.h>
  27.  
  28. #include <sys/socket.h>
  29. #include <netinet/in.h>
  30. #include <arpa/inet.h>
  31. #include <signal.h>
  32. #include <netdb.h>
  33.  
  34.  
  35. #include <common/debug.h>
  36. #include <common/portability.h>
  37.  
  38. #define    MSQL_ADT
  39. #include "msql_priv.h"
  40. #include "msql.h"
  41. #include "y.tab.h"
  42.  
  43. int     command,
  44.     notnullflag,
  45.     keyflag,
  46.     outSock;
  47.  
  48. char     *curDB,
  49.     *arrayLen;
  50.  
  51. cond_t    *condHead = NULL;
  52.  
  53. field_t    *fieldHead = NULL,
  54.     *lastField = NULL;
  55.  
  56. order_t    *orderHead = NULL;
  57.  
  58. tname_t    *tableHead = NULL;
  59.  
  60. static    cond_t    *condTail = NULL;
  61. static    field_t    *fieldTail = NULL;
  62. static    order_t    *orderTail = NULL;
  63. static    tname_t    *tableTail = NULL;
  64. static     int    havePriKey = 0;
  65.  
  66.  
  67. #define    malloc(L)    Malloc(L,__FILE__,__LINE__)
  68. #define    free(A)        Free(A,__FILE__,__LINE__)
  69. #define    safeFree(x)    {if (x) { (void) free(x); x = NULL; }}
  70. #define REG        register
  71.  
  72.  
  73. extern    char    *packet;
  74.  
  75.  
  76.  
  77. /****************************************************************************
  78. **     _msqlClean - clean out the internal structures
  79. **
  80. **    Purpose    : Free all space and reset structures after a query
  81. **    Args    : None
  82. **    Returns    : Nothing
  83. **    Notes    : Updates all public data structures
  84. */
  85.  
  86. msqlClean()
  87. {
  88.     register field_t    *curField, *tmpField;
  89.     register cond_t        *curCond, *tmpCond;
  90.     register order_t     *curOrder, *tmpOrder;
  91.     register tname_t    *curTable, *tmpTable;
  92.  
  93.     msqlTrace(TRACE_IN,"msqlClean()");
  94.     command = 0;
  95.     havePriKey = 0;
  96.  
  97.     /*
  98.     ** blow away the table list from the query
  99.     */
  100.     curTable = tableHead;
  101.     while(curTable)
  102.     {
  103.         tmpTable = curTable;
  104.         curTable = curTable->next;
  105.         (void)free(tmpTable);
  106.     }
  107.  
  108.  
  109.     /*
  110.     ** blow away the field list from the query
  111.     */
  112.     curField = fieldHead;
  113.     while(curField)
  114.     {
  115.         freeValue(curField->value);
  116.         tmpField = curField;
  117.         curField = curField->next;
  118.         (void)free(tmpField);
  119.     }
  120.  
  121.     /*
  122.     ** Blow away the condition list from the query
  123.     */
  124.     curCond = condHead;
  125.     while(curCond)
  126.     {
  127.         freeValue(curCond->value);
  128.         curCond->op = curCond->bool = 0;
  129.         tmpCond = curCond;
  130.         curCond = curCond->next;
  131.         (void)free(tmpCond);
  132.     }
  133.     curOrder = orderHead;
  134.     while(curOrder)
  135.     {
  136.         curOrder->dir = 0;
  137.         tmpOrder = curOrder;
  138.         curOrder = curOrder->next;
  139.         (void)free(tmpOrder);
  140.     }
  141.  
  142.  
  143.     /*
  144.     ** Reset the list pointers
  145.     */
  146.  
  147.     condHead = condTail = (cond_t *) NULL;
  148.     fieldHead = fieldTail = lastField = (field_t *) NULL;
  149.     orderHead = orderTail = (order_t *) NULL;
  150.     tableHead = tableTail = (tname_t *) NULL;
  151.  
  152.     msqlBackendClean();
  153.  
  154.     msqlTrace(TRACE_OUT,"msqlClean()");
  155. }
  156.  
  157.  
  158.  
  159. ident_t *msqlCreateIdent(seg1,seg2)
  160.     char    *seg1,
  161.         *seg2;
  162. {
  163.     ident_t    *new;
  164.  
  165.     msqlTrace(TRACE_IN,"msqlCreateIdent()");
  166.     if (seg1)
  167.     {
  168.         if (strlen(seg1) > NAME_LEN)
  169.         {
  170.             sprintf(packet,
  171.                 "-1:Identifier name '%s' too long\n",seg1);
  172.             writePkt(outSock);
  173.             msqlTrace(TRACE_OUT,"msqlCreateIdent()");
  174.             return(NULL);
  175.         }
  176.     }
  177.     if (seg2)
  178.     {
  179.         if (strlen(seg2) > NAME_LEN)
  180.         {
  181.             sprintf(packet,
  182.                 "-1:Identifier name '%s' too long\n",seg2);
  183.             writePkt(outSock);
  184.             msqlTrace(TRACE_OUT,"msqlCreateIdent()");
  185.             return(NULL);
  186.         }
  187.     }
  188.     new = (ident_t *)malloc(sizeof(ident_t));
  189.     if (seg1)
  190.     {
  191.         (void)strcpy(new->seg1,seg1);
  192.     }
  193.     if (seg2)
  194.     {
  195.         (void)strcpy(new->seg2,seg2);
  196.     }
  197.     msqlTrace(TRACE_OUT,"msqlCreateIdent()");
  198.     return(new);
  199. }
  200.  
  201.  
  202.  
  203. static u_char expandEscape(c,remain)
  204.     u_char    *c;
  205.     int    remain;
  206. {
  207.     u_char    ret;
  208.  
  209.     switch(*c)
  210.     {
  211.         case 'n':
  212.             ret = '\n';
  213.             break;
  214.         case 't':
  215.             ret = '\t';
  216.             break;
  217.         case 'r':
  218.             ret = '\r';
  219.             break;
  220.         case 'b':
  221.             ret = '\b';
  222.             break;
  223.         default:
  224.             ret = *c;
  225.             break;
  226.     }
  227.     return(ret);
  228. }
  229.  
  230.  
  231.  
  232. val_t *msqlCreateValue(textRep,type,tokLen)
  233.     u_char    *textRep;
  234.     int    type,
  235.         tokLen;
  236. {
  237.     val_t    *new;
  238.     int    length,
  239.         remain,
  240.         match;
  241.     REG     u_char    *cp,
  242.             *cp2;
  243.     static    u_char nullVal[] = "null";
  244.  
  245.     msqlTrace(TRACE_IN,"msqlCreateValue()");
  246.     new = (val_t *)malloc(sizeof(val_t));
  247.     new->type = type;
  248.     new->dataLen = tokLen;
  249.     switch(type)
  250.     {
  251.         case NULL_TYPE:
  252.             new->nullVal = 1;
  253.             break;
  254.         case IDENT_TYPE:
  255.             new->val.identVal = (ident_t *)textRep;
  256.             break;
  257.  
  258.         case CHAR_TYPE:
  259.             remain = length = tokLen - 2;
  260.             new->val.charVal = (u_char *)malloc(length+1);
  261.             cp = textRep+1;
  262.             cp2 = new->val.charVal;
  263.             while(remain)
  264.             {
  265.                 if (*cp == '\\')
  266.                 {
  267.                     remain--;
  268.                     *cp2 = expandEscape(++cp,remain);
  269.                     if (*cp2)
  270.                     {
  271.                         cp2++;
  272.                         cp++;
  273.                         remain--;
  274.                     }
  275.                 }
  276.                 else
  277.                 {
  278.                     *cp2++ = *cp++;
  279.                     remain--;
  280.                 }
  281.             }
  282.             break;
  283.  
  284.         case INT_TYPE:
  285.             new->val.intVal = atoi(textRep);
  286.             break;
  287.  
  288.         case REAL_TYPE:
  289.             sscanf((char *)textRep ,"%lg",&new->val.realVal);
  290.             break;
  291.     }
  292.     msqlTrace(TRACE_OUT,"msqlCreateValue()");
  293.     return(new);
  294. }
  295.  
  296.  
  297. val_t *fillValue(val,type,length)
  298.     char    *val;
  299.     int    type,
  300.         length;
  301. {
  302.     val_t    *new;
  303.  
  304.     msqlTrace(TRACE_IN,"fillValue()");
  305.     new = (val_t *)malloc(sizeof(val_t));
  306.     new->type = type;
  307.     new->nullVal = 0;
  308.     switch(type)
  309.     {
  310.         case CHAR_TYPE:
  311.             new->val.charVal = (u_char *)malloc(length+1);
  312.             (void)bcopy(val,new->val.charVal,length);
  313.             break;
  314.  
  315.         case INT_TYPE:
  316. #ifndef _CRAY
  317.             new->val.intVal = (int) * (int *)val;
  318. #else
  319.             new->val.intVal = unpackInt32(val);
  320. #endif
  321.             break;
  322.  
  323.         case REAL_TYPE:
  324.             new->val.realVal = (double) * (double *)val;
  325.             break;
  326.     }
  327.     msqlTrace(TRACE_OUT,"fillValue()");
  328.     return(new);
  329. }
  330.  
  331.  
  332. val_t *nullValue()
  333. {
  334.     val_t    *new;
  335.  
  336.     new = (val_t *)malloc(sizeof(val_t));
  337.     new->nullVal = 1;
  338.     return(new);
  339. }
  340.  
  341.  
  342.  
  343. freeValue(val)
  344.     val_t    *val;
  345. {
  346.     msqlTrace(TRACE_IN,"freeValue()");
  347.     if (!val)
  348.     {
  349.         msqlTrace(TRACE_OUT,"freeValue()");
  350.         return;
  351.     }
  352.     switch(val->type)
  353.     {
  354.         case IDENT_TYPE:
  355.             (void)free(val->val.identVal);
  356.             break;
  357.         case CHAR_TYPE:
  358.             if (!val->nullVal)
  359.                 (void)free(val->val.charVal);
  360.             break;
  361.     }
  362.     (void)free(val);
  363.     msqlTrace(TRACE_OUT,"freeValue()");
  364. }
  365.  
  366.  
  367.  
  368. /****************************************************************************
  369. **     _msqlAddField - add a field definition to the list
  370. **
  371. **    Purpose    : store field details from the query for later use
  372. **    Args    : field name, field type, field length, value
  373. **    Returns    : Nothing
  374. **    Notes    : Depending on the query in process, only some of the
  375. **          args will be supplied.  eg. a SELECT doesn't use the
  376. **          type arg.  The length arg is only used during a create
  377. **          if the field is of type CHAR
  378. */
  379.  
  380. int msqlAddField(ident,type,length,notNull,priKey)
  381.     ident_t    *ident;
  382.     int     type;
  383.     char    *length;
  384.     int    notNull,
  385.         priKey;
  386. {
  387.     register field_t    *new;
  388.     char    *name,
  389.         *table;
  390.  
  391.     msqlTrace(TRACE_IN,"msqlAddField()");
  392.  
  393.     if (priKey)
  394.     {
  395.         if (havePriKey)
  396.         {
  397.             sprintf(packet,"-1:Can't have multiple primary keys\n");
  398.             writePkt(outSock);
  399.             msqlTrace(TRACE_OUT,"msqlAddField()");
  400.             return(-1);
  401.  
  402.         }
  403.         else
  404.         {
  405.             havePriKey = 1;
  406.         }
  407.     }
  408.  
  409.  
  410.     if (*(ident->seg2))
  411.     {
  412.         name = ident->seg2;
  413.         table = ident->seg1;
  414.     }
  415.     else
  416.     {
  417.         name = ident->seg1;
  418.         table = NULL;
  419.     }
  420.     new = (field_t *)malloc(sizeof(field_t));
  421.     if (table)
  422.     {
  423.         (void)strncpy(new->table,table,NAME_LEN - 1);
  424.     }
  425.     (void)strncpy(new->name,name,NAME_LEN - 1);
  426.     if (notNull)
  427.     {
  428.         new->flags |= NOT_NULL_FLAG;
  429.     }
  430.     if (priKey)
  431.     {
  432.         new->flags |= PRI_KEY_FLAG;
  433.         new->flags |= NOT_NULL_FLAG;
  434.     }
  435.     switch(type)
  436.     {
  437.         case INT:
  438.             new->type = INT_TYPE;
  439.             new->length = 4;
  440.             break;
  441.  
  442.         case CHAR:
  443.             new->type = CHAR_TYPE;
  444.             new->length = atoi(length);
  445.             break;
  446.  
  447.         case REAL:
  448.             new->type = REAL_TYPE;
  449.             new->length = sizeof(double);
  450.             break;
  451.  
  452.         default:
  453.             new->type = 0;
  454.             new->length = 0;
  455.             break;
  456.     }
  457.     if (!fieldHead)
  458.     {
  459.         fieldHead = fieldTail = new;
  460.     }
  461.     else
  462.     {
  463.         fieldTail->next = new;
  464.         fieldTail = new;
  465.     }
  466.     free(ident);
  467.     msqlTrace(TRACE_OUT,"msqlAddField()");
  468.     return(0);
  469. }
  470.  
  471.  
  472. msqlAddFieldValue(value)
  473.     val_t    *value;
  474. {
  475.     register field_t    *fieldVal;
  476.     u_char    *buf;
  477.  
  478.     msqlTrace(TRACE_IN,"msqlAddFieldValue()");
  479.     if (!lastField)
  480.     {
  481.         lastField = fieldVal = fieldHead;
  482.     }
  483.     else
  484.     {    
  485.         fieldVal = lastField->next;
  486.         lastField = lastField->next;
  487.     }
  488.     if (fieldVal)
  489.     {
  490.         if (fieldVal->type == CHAR_TYPE)
  491.         {
  492.             buf = (u_char *)malloc(fieldVal->length+1);
  493.             bcopy(value->val.charVal,buf,value->dataLen);
  494.             free(value->val.charVal);
  495.             value->val.charVal = buf;
  496.         }
  497.         fieldVal->value = value;
  498.     }
  499.     msqlTrace(TRACE_OUT,"msqlAddFieldValue()");
  500. }
  501.  
  502.  
  503.  
  504.  
  505. /****************************************************************************
  506. **     _msqlAddCond  -  add a conditional spec to the list
  507. **
  508. **    Purpose    : Store part of a "where_clause" for later use
  509. **    Args    : field name, test op, value, bool (ie. AND | OR)
  510. **    Returns    : Nothing
  511. **    Notes    : the BOOL field is only provided if this is not the first
  512. **          element of a where_clause.
  513. */
  514.  
  515. msqlAddCond(ident,op,value,bool)
  516.     ident_t    *ident;
  517.     int    op;
  518.     val_t    *value;
  519.     int    bool;
  520. {
  521.     register cond_t    *new;
  522.     char    *name,
  523.         *table;
  524.  
  525.     msqlTrace(TRACE_IN,"msqlAddCond()");
  526.  
  527.     if (*(ident->seg2))
  528.     {
  529.         name = ident->seg2;
  530.         table = ident->seg1;
  531.     }
  532.     else
  533.     {
  534.         name = ident->seg1;
  535.         table = NULL;
  536.     }
  537.  
  538.     new = (cond_t *)malloc(sizeof(cond_t));
  539.     (void)strcpy(new->name,name);
  540.     if (table)
  541.     {
  542.         (void)strcpy(new->table,table);
  543.     }
  544.     
  545.     new->op = op;
  546.     new->bool = bool;
  547.     new->value = value;
  548.  
  549.     if (!condHead)
  550.     {
  551.         condHead = condTail = new;
  552.     }
  553.     else
  554.     {
  555.         condTail->next = new;
  556.         condTail = new;
  557.     }
  558.     free(ident);
  559.     msqlTrace(TRACE_OUT,"msqlAddCond()");
  560. }
  561.  
  562.  
  563.  
  564. /****************************************************************************
  565. **     _msqlAddOrder  -  add an order definition to the list
  566. **
  567. **    Purpose    : Store part of an "order_clause"
  568. **    Args    : field name, order direction (ie. ASC or DESC)
  569. **    Returns    : Nothing
  570. **    Notes    : 
  571. */
  572.  
  573. msqlAddOrder(ident,dir)
  574.     ident_t    *ident;
  575.     int    dir;
  576. {
  577.     register order_t    *new;
  578.  
  579.     msqlTrace(TRACE_IN,"msqlAddOrder()");
  580.  
  581.     new = (order_t *)malloc(sizeof(order_t));
  582.     if (*ident->seg1)
  583.     {
  584.         (void)strcpy(new->table,ident->seg1);
  585.     }
  586.     (void)strcpy(new->name,ident->seg2);
  587.     new->dir = dir;
  588.     if (!orderHead)
  589.     {
  590.         orderHead = orderTail = new;
  591.     }
  592.     else
  593.     {
  594.         orderTail->next = new;
  595.         orderTail = new;
  596.     }
  597.     free(ident);
  598.     msqlTrace(TRACE_OUT,"msqlAddOrder()");
  599. }
  600.  
  601.  
  602.  
  603.  
  604. msqlAddTable(name,alias)
  605.     char    *name,
  606.         *alias;
  607. {
  608.     register tname_t    *new;
  609.  
  610.     msqlTrace(TRACE_IN,"msqlAddTable()");
  611.  
  612.     new = (tname_t *)malloc(sizeof(tname_t));
  613.     if (alias)
  614.     {
  615.         (void)strcpy(new->name,alias);
  616.         (void)strcpy(new->cname,name);
  617.         (void)free(name);
  618.         (void)free(alias);
  619.     }
  620.     else
  621.     {
  622.         (void)strcpy(new->name,name);
  623.         *(new->cname) = 0;
  624.         (void)free(name);
  625.     }
  626.     if (!tableHead)
  627.     {
  628.         tableHead = tableTail = new;
  629.     }
  630.     else
  631.     {
  632.         tableTail->next = new;
  633.         tableTail = new;
  634.     }
  635.     msqlTrace(TRACE_OUT,"msqlAddTable()");
  636. }
  637.  
  638.  
  639.  
  640.  
  641.  
  642.  
  643.  
  644. msqlSetDB(db)
  645.     char    *db;
  646. {
  647.     curDB = db;
  648. }
  649.  
  650.  
  651.  
  652. /****************************************************************************
  653. **     _msqlProcessQuery  -  send to query to the approp routine
  654. **
  655. **    Purpose    : Call the required routine to build the native query
  656. **    Args    : None
  657. **    Returns    : Nothing
  658. **    Notes    : Global command variable used.  This is called when the
  659. **          end of an individual query is found in the miniSQL code
  660. **          and provides the hooks into the per-database routines.
  661. */
  662.  
  663.  
  664.  
  665. msqlProcessQuery()
  666. {
  667.     int    res;
  668.  
  669.     msqlTrace(TRACE_IN,"msqlProcessQuery()");
  670.     if (!curDB)
  671.     {
  672.         sprintf(packet,"-1:No current database\n");
  673.         writePkt(outSock);
  674.         msqlDebug(MOD_ERR,"No current database\n");
  675.         msqlTrace(TRACE_OUT,"msqlProcessQuery()");
  676.         return;
  677.     }
  678.     switch(command)
  679.     {
  680.         case SELECT: 
  681.             setProcTitle("Q=Select");
  682.             if (!msqlCheckPerms(READ_ACCESS))
  683.             {
  684.                 sprintf(packet,"-1:Access Denied\n");
  685.                 writePkt(outSock);
  686.                 msqlTrace(TRACE_OUT,"msqlProcessQuery()");
  687.                 return;
  688.             }
  689.             res = msqlSelect(tableHead,fieldHead,condHead,
  690.                 orderHead,curDB);
  691.             break;
  692.         case CREATE: 
  693.             setProcTitle("Q=Create");
  694.             if (!msqlCheckPerms(WRITE_ACCESS))
  695.             {
  696.                 sprintf(packet,"-1:Access Denied\n");
  697.                 writePkt(outSock);
  698.                 msqlTrace(TRACE_OUT,"msqlProcessQuery()");
  699.                 return;
  700.             }
  701.             res = msqlCreate(tableHead->name,fieldHead,curDB);
  702.             break;
  703.         case UPDATE: 
  704.             setProcTitle("Q=Update");
  705.             if (!msqlCheckPerms(RW_ACCESS))
  706.             {
  707.                 sprintf(packet,"-1:Access Denied\n");
  708.                 writePkt(outSock);
  709.                 msqlTrace(TRACE_OUT,"msqlProcessQuery()");
  710.                 return;
  711.             }
  712.             res = msqlUpdate(tableHead->name,fieldHead,condHead,
  713.                 curDB);
  714.             break;
  715.         case INSERT: 
  716.             setProcTitle("Q=Insert");
  717.             if (!msqlCheckPerms(WRITE_ACCESS))
  718.             {
  719.                 sprintf(packet,"-1:Access Denied\n");
  720.                 writePkt(outSock);
  721.                 msqlTrace(TRACE_OUT,"msqlProcessQuery()");
  722.                 return;
  723.             }
  724.             res = msqlInsert(tableHead->name,fieldHead,curDB);
  725.             break;
  726.         case DELETE: 
  727.             setProcTitle("Q=Delete");
  728.             if (!msqlCheckPerms(WRITE_ACCESS))
  729.             {
  730.                 sprintf(packet,"-1:Access Denied\n");
  731.                 writePkt(outSock);
  732.                 msqlTrace(TRACE_OUT,"msqlProcessQuery()");
  733.                 return;
  734.             }
  735.             res = msqlDelete(tableHead->name,condHead,curDB);
  736.             break;
  737.         case DROP: 
  738.             setProcTitle("Q=Drop");
  739.             if (!msqlCheckPerms(WRITE_ACCESS))
  740.             {
  741.                 sprintf(packet,"-1:Access Denied\n");
  742.                 writePkt(outSock);
  743.                 msqlTrace(TRACE_OUT,"msqlProcessQuery()");
  744.                 return;
  745.             }
  746.             res = msqlDrop(tableHead->name,curDB);
  747.             break;
  748.     }
  749.     if (res < 0)
  750.     {
  751.         extern    char    errMsg[];
  752.         char    errBuf[180];
  753.  
  754.         sprintf(packet,"-1:%s\n",errMsg);
  755.         msqlTrace(TRACE_OUT,"msqlProcessQuery()");
  756.         writePkt(outSock);
  757.     }
  758.     msqlTrace(TRACE_OUT,"msqlProcessQuery()");
  759. }
  760.  
  761.  
  762. msqlQueryOverrunError(txt)
  763.     char    *txt;
  764. {
  765.  
  766.     msqlTrace(TRACE_IN,"msqlQueryOverrunError()");
  767.     sprintf(packet,"-1:Syntax error.  Bad text after query. '%s'\n",txt);
  768.     writePkt(outSock);
  769.     msqlTrace(TRACE_OUT,"msqlQueryOverrunError()");
  770. }
  771.  
  772.  
  773.  
  774.  
  775. char *msqlParseQuery(inBuf,sock)
  776.         char    *inBuf;
  777.         int     sock;
  778. {
  779.     msqlTrace(TRACE_IN,"msqlParseQuery()");
  780.         outSock = sock;
  781.         msqlInitScanner(inBuf);
  782.         yyparse();
  783.     msqlTrace(TRACE_OUT,"msqlParseQuery()");
  784. }
  785.  
  786.